package com.example.zlw.proxydemo;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * Created by ZLW on 2017/6/26.
 */

public class AmsUtils {
    private Context context;
    private Class<?> proxyActivity;
    private Object activityThreadValue;

    public AmsUtils(Context context, Class<?> proxyActivity) {
        this.context = context;
        this.proxyActivity = proxyActivity;
    }


    /**
     * 通过hook替换Intent
     */

    public void hookAms() {
        try {
            Class<?> aClass = Class.forName("android.app.ActivityManagerNative");
            Field gDefault = aClass.getDeclaredField("gDefault");
            gDefault.setAccessible(true);
            Object gDefaultValue = gDefault.get(null);
            Class<?> aClass1 = Class.forName("android.util.Singleton");
            Field mInstance = aClass1.getDeclaredField("mInstance");
            mInstance.setAccessible(true);
            Object IActivityManagerValue = mInstance.get(gDefaultValue);

            //创建一个新的接口对象来动态代理
            Class<?> IActivityManagerProxy = Class.forName("android.app.IActivityManager");

            AmsInvocationHandler handler = new AmsInvocationHandler(IActivityManagerValue);

            //代理对象
            Object proxyInstance = Proxy.newProxyInstance(context.getClassLoader(),
                    new Class<?>[]{IActivityManagerProxy}, handler);

            //注入代理
            mInstance.set(gDefaultValue, proxyInstance);

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    class AmsInvocationHandler implements InvocationHandler {
        private Object IActivityManagerValue;

        public AmsInvocationHandler(Object AmsInvocationHandler) {
            this.IActivityManagerValue = AmsInvocationHandler;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //把非法的Intent换成合法的Intent(偷天换日)
            if ("startActivity".contains(method.getName())) {
                Intent intent = null;
                int index = 0;
                for (int i = 0; i < args.length; i++) {
                    if (args[i] instanceof Intent) {
                        //这是个非法的Intent,是我们实际要启动的Intent,这个Activity没有再清单中注册
                        intent = (Intent) args[i];
                        index = i;
                        break;
                    }
                }

                //创建一个合法的意图
                Intent proxyIntent = new Intent();
                //把我们实际要启动的那个意图(非法的意图) 带过去
                proxyIntent.putExtra("oldIntent", intent);
                ComponentName component = new ComponentName(context, proxyActivity);
                proxyIntent.setComponent(component);
                args[index] = proxyIntent;
                return method.invoke(IActivityManagerValue, args);
            }

            return method.invoke(IActivityManagerValue, args);
        }

    }

    public void hookSysHandler() {
        try {
            Class<?> aClass = Class.forName("android.app.ActivityThread");
            Field sCurrentActivityThread = aClass.getDeclaredField("sCurrentActivityThread");

            //静态对象传一个null就可以获取了
            sCurrentActivityThread.setAccessible(true);
            //ActivityThread对象 拿到这个对象可以干很多的坏事了
            activityThreadValue = sCurrentActivityThread.get(null);

            //获取ActivityThread中的Handler字段
            Field mH = aClass.getDeclaredField("mH");
            mH.setAccessible(true);
            //获取Activity Thread对象的值
            Handler handler = (Handler) mH.get(activityThreadValue);
            Field mCallback = Handler.class.getDeclaredField("mCallback");
            mCallback.setAccessible(true);
            mCallback.set(handler, new ActivityThreadHandlerCallback(handler));


        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    class ActivityThreadHandlerCallback implements Handler.Callback {

        private Handler mH;

        ActivityThreadHandlerCallback(Handler h) {
            this.mH = h;
        }

        @Override
        public boolean handleMessage(Message msg) {
            if (msg.what == 100) {
                handlerLaunchActivity(msg);
            }
            //按照程序原来的调用
            mH.handleMessage(msg);
            return true;
        }
    }

    private void handlerLaunchActivity(Message msg) {
        Object obj = msg.obj;//ActivityClientRecord
        try {

            //拿到ActivityClientRecord 中的Intent字段
            Field intentField = obj.getClass().getDeclaredField("intent");
            intentField.setAccessible(true);
            //获取Intentd对象的值
            Intent proxyIntent = (Intent) intentField.get(obj);
            //获取合法意图带着的真实的意图
            Intent oldIntent = (Intent) proxyIntent.getParcelableExtra("oldIntent");
            if (oldIntent != null) {
                //将合法的意图替换成非法的意图,也就是我们真实要跳转的界面
                proxyIntent.setComponent(oldIntent.getComponent());
            }

        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}